/**
 * 时间工具类
 */
class DateUtils {
  /**
   * 格式化时间
   * @param {Date|number|string} time - 时间对象、时间戳或时间字符串
   * @param {string} format - 格式，默认'yyyy-MM-dd hh:mm:ss'
   * @returns {string} 格式化后的时间字符串
   */
  static formatTime(time, format = 'yyyy-MM-dd hh:mm:ss') {
    if (!time) return ''

    let date
    if (time instanceof Date) {
      date = time
    } else if (typeof time === 'number') {
      // 处理时间戳（判断是秒还是毫秒）
      date = new Date(time.toString().length === 10 ? time * 1000 : time)
    } else if (typeof time === 'string') {
      // 处理字符串时间
      if (/^\d+$/.test(time)) {
        date = new Date(parseInt(time.length === 10 ? time * 1000 : time))
      } else {
        date = new Date(time.replace(/-/g, '/'))
      }
    } else {
      return ''
    }

    if (isNaN(date.getTime())) return ''

    const o = {
      'M+': date.getMonth() + 1, // 月份
      'd+': date.getDate(), // 日
      'h+': date.getHours(), // 小时
      'm+': date.getMinutes(), // 分
      's+': date.getSeconds(), // 秒
      'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
      S: date.getMilliseconds(), // 毫秒
    }

    if (/(y+)/.test(format)) {
      format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
    }

    for (const k in o) {
      if (new RegExp('(' + k + ')').test(format)) {
        format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length))
      }
    }
    return format
  }

  /**
   * 获取当前时间戳
   * @returns {number} 当前时间戳(毫秒)
   */
  static now() {
    return Date.now()
  }

  /**
   * 获取当前时间戳(秒)
   * @returns {number} 当前时间戳(秒)
   */
  static nowSeconds() {
    return Math.floor(Date.now() / 1000)
  }

  /**
   * 判断当前时间是否大于指定小时
   * @param {number} hour 要比较的小时数 (0-23)
   * @returns {boolean} 是否大于指定小时
   */
  static isAfterHour(hour = 12) {
    const now = new Date()
    const options = {
      hour: 'numeric',
      hour12: false,
      timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    }
    const currentHour = parseInt(now.toLocaleString('en-US', options))
    return currentHour > 12
  }

  /**
   * 将时间转换为友好显示格式
   * @param {Date|number|string} time - 时间
   * @param {string} format - 超过30天的显示格式，默认'yyyy-MM-dd'
   * @returns {string} 友好时间字符串
   */
  static friendlyTime(time, format = 'yyyy-MM-dd') {
    if (!time) return ''

    const date = this._parseDate(time)
    if (!date) return ''

    const now = new Date()
    const diff = (now - date) / 1000 // 时间差(秒)

    if (diff < 60) {
      return '刚刚'
    } else if (diff < 3600) {
      return Math.floor(diff / 60) + '分钟前'
    } else if (diff < 86400) {
      return Math.floor(diff / 3600) + '小时前'
    } else if (diff < 2592000) {
      // 30天内
      return Math.floor(diff / 86400) + '天前'
    } else {
      return this.formatTime(date, format)
    }
  }

  /**
   * 获取两个时间之间的天数差
   * @param {Date|number|string} time1 - 时间1
   * @param {Date|number|string} time2 - 时间2
   * @returns {number} 天数差
   */
  static getDaysBetween(time1, time2) {
    const date1 = this._parseDate(time1)
    const date2 = this._parseDate(time2)
    if (!date1 || !date2) return 0

    const diff = Math.abs(date1.getTime() - date2.getTime())
    return Math.floor(diff / (1000 * 60 * 60 * 24))
  }
  /**
   * 是否为今天
   * @param {Date|number|string} time - 时间
   * @returns {boolean} 是否为今天
   */
  static isToday(time) {
    const date = this._parseDate(time)
    if (!date) return false

    const today = new Date()
    return date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth() && date.getDate() === today.getDate()
  }

  /**
   * 获取某个月的天数
   * @param {number} year - 年
   * @param {number} month - 月(1-12)
   * @returns {number} 天数
   */
  static getDaysInMonth(year, month) {
    return new Date(year, month, 0).getDate()
  }

  /**
   * 是否为闰年
   * @param {number} year - 年
   * @returns {boolean} 是否为闰年
   */
  static isLeapYear(year) {
    return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0
  }

  /**
   * 时间加减
   * @param {Date|number|string} time - 时间
   * @param {number} amount - 数量
   * @param {string} unit - 单位('year','month','day','hour','minute','second')
   * @returns {Date} 计算后的日期
   */
  static addTime(time, amount, unit) {
    const date = this._parseDate(time)
    if (!date) return null

    const map = {
      year: 'FullYear',
      month: 'Month',
      day: 'Date',
      hour: 'Hours',
      minute: 'Minutes',
      second: 'Seconds',
    }

    const method = map[unit]
    if (!method) return date

    date[`set${method}`](date[`get${method}`]() + amount)
    return date
  }

  /**
   * 解析时间为Date对象
   * @private
   * @param {Date|number|string} time - 时间
   * @returns {Date|null} Date对象或null
   */
  static _parseDate(time) {
    if (!time) return null
    if (time instanceof Date) return time

    let date
    if (typeof time === 'number') {
      date = new Date(time.toString().length === 10 ? time * 1000 : time)
    } else if (typeof time === 'string') {
      if (/^\d+$/.test(time)) {
        date = new Date(parseInt(time.length === 10 ? time * 1000 : time))
      } else {
        date = new Date(time.replace(/-/g, '/'))
      }
    }

    return date && !isNaN(date.getTime()) ? date : null
  }
  /**
   * 获取格式化的第二天日期字符串
   * @param {string} format 格式，如 'YYYY-MM-DD'
   * @returns {string} 格式化后的日期字符串
   */
  static getFormattedNextDay(format = 'YYYY-MM-DD') {
    const tomorrow = new Date()
    tomorrow.setDate(tomorrow.getDate() + 1)

    const year = tomorrow.getFullYear()
    const month = String(tomorrow.getMonth() + 1).padStart(2, '0')
    const day = String(tomorrow.getDate()).padStart(2, '0')

    return format.replace('YYYY', year).replace('MM', month).replace('DD', day)
  }
  /**
   * 获取格式化的第1天日期字符串
   * @param {string} format 格式，如 'YYYY-MM-DD'
   * @returns {string} 格式化后的日期字符串
   */
  static getFormattedTodayDay(format = 'YYYY-MM-DD') {
    const tomorrow = new Date()
    tomorrow.setDate(tomorrow.getDate())

    const year = tomorrow.getFullYear()
    const month = String(tomorrow.getMonth() + 1).padStart(2, '0')
    const day = String(tomorrow.getDate()).padStart(2, '0')

    return format.replace('YYYY', year).replace('MM', month).replace('DD', day)
  }
}

export default DateUtils
